#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER
	
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" 
                || ls.getSymCour()=="lire" 
                || ls.getSymCour()=="ecrire" 
                || ls.getSymCour()=="si" 
                || ls.getSymCour()=="tantque" 
                || ls.getSymCour()=="repeter" 
                || ls.getSymCour()=="pour");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst() {
// <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>| <instLire> | <instEcrire> | <instPour>

	if (ls.getSymCour()=="lire")
	{
		instLire();
	}
	else if (ls.getSymCour()=="ecrire")
	{
		instEcrire();
	}
	else if (ls.getSymCour()=="<VARIABLE>")
	{
		affectation();
	}
	else if (ls.getSymCour()=="si")
	{
		instSi();
	}
	else if (ls.getSymCour()=="tantque")
	{
		instTq();
	}
	else if (ls.getSymCour()=="repeter")
	{
		instRepeter();
	}
	else if (ls.getSymCour()=="pour")
	{
		instPour();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>

	sauterSymCour("<VARIABLE>");
	sauterSymCour("=");
	expression();
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expEt()
//<expEt> ::= <relation> { <opEt> <relation> }
{
	relation();
	while(ls.getSymCour()=="et")
	{
		opEt();
		relation();
	}
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expOu()
//<expOu> ::= <expEt> { <opOu> <expEt> }
{
	expEt();
	while(ls.getSymCour()=="ou")
	{
		opOu();
		expEt();
	}
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::relation()
//<relation> ::= <expression> { <opRel> <expression> }
{
	expression();
	while(ls.getSymCour()=="==" 
                || ls.getSymCour()=="!=" 
                || ls.getSymCour()=="<" 
                || ls.getSymCour()==">" 
                || ls.getSymCour()=="<=" 
                || ls.getSymCour()==">=")
	{
		opRel();
		expression();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
//<expression> ::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme() {
// <terme> ::= <facteur> {<opMult> <facteur>}

	facteur();
	while (ls.getSymCour()=="*" || ls.getSymCour()=="/") {
		opMult();
		facteur();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  <opUnaire> <expOu> | (<expOu>)

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();
	else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
		ls.suivant();
		expOu();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expOu();
		sauterSymCour(")");
	} else
		erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opAdd()
// <opAdd> ::= + | -
{
	if(ls.getSymCour()=="+" || ls.getSymCour()=="-")
	{
		ls.suivant();
	}
	else
		erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
// <opMult> ::= * | /
{
	if(ls.getSymCour()=="*" || ls.getSymCour()=="/")
	{
		ls.suivant();
	}
	else
		erreur("<opMult>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opUnaire()
// <opMult> ::= - | non
{
	if(ls.getSymCour()=="-" || ls.getSymCour()=="non")
	{
		ls.suivant();
	}
	else
		erreur("<opUnaire>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opOu()
// <opOu> ::= ou
{
	if (ls.getSymCour()=="ou")
	{
		ls.suivant();
	}
	else
		erreur("<opOu>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opEt()
// <opEt> ::= et
{
	if (ls.getSymCour()=="et")
	{
		ls.suivant();
	}
	else
		erreur("<opEt>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opRel()
// <opRel> ::= == | != | < | <= | > | >=                               
{
	if(ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<" || ls.getSymCour()==">" || ls.getSymCour()=="<=" || ls.getSymCour()==">=")
	{
		ls.suivant();
	}
	else
		erreur("<opRel>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instLire()
// <instLire> ::= lire ( <variable> )
{
	ls.suivant();
	sauterSymCour("(");
	if (ls.getSymCour()=="<VARIABLE>")
	{
		ls.suivant();
	}
	else
		erreur("<instLire>");

	sauterSymCour(")");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instEcrire()
// <instEcrire> ::= ecrire (<expression> | <chaine> )
{
	ls.suivant();
	sauterSymCour("(");
	if (ls.getSymCour()=="<CHAINE>")
	{
		ls.suivant();
	}
	else
		expression();

	sauterSymCour(")");
}
////////////////////////////////////////////////////////////////////////////////	
void LecteurPhraseSimple::instSi() {
//<instSi> ::= si ( <expOu>) <seqInst> {sinonsi ( <expOu> ) <seqInst> } [sinon <seqInst> ] finsi
	sauterSymCour("si");
	sauterSymCour("(");
	expOu();
	sauterSymCour(")");
	seqInst();
	while (ls.getSymCour() == "sinonsi")
	{
		sauterSymCour("sinonsi");
		sauterSymCour("(");
		expOu();
		sauterSymCour(")");
		seqInst();

	}
	if (ls.getSymCour() == "sinon")
	{
		sauterSymCour("sinon");
		seqInst();
	}
	sauterSymCour("finsi");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instTq() {
//<instTq> ::= tantque ( <expOu> ) <seqInst> fintantque
	sauterSymCour("tantque");
	sauterSymCour("(");
	expOu();
	sauterSymCour(")");
	seqInst();
	sauterSymCour("fintantque");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instRepeter() {
//<instRepeter> ::= repeter <seqInst> jusqua (<expOu>)
	sauterSymCour("repeter");
	seqInst();
	sauterSymCour("jusqua");
	sauterSymCour("(");	
	expOu();	
	sauterSymCour(")");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instPour() {
// <instPour> ::= pour <variable> allant de <variable> -> <variable> avec <affectation> <seqInst> finpour
	sauterSymCour("pour");

	if (ls.getSymCour()=="<VARIABLE>")
	{
		ls.suivant();
	}
	else
		erreur("<instPour>");

	sauterSymCour("allant");
	sauterSymCour("de");

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
	{
		ls.suivant();
	}
	else
		erreur("<instPour>");

	sauterSymCour("->");

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
	{
		ls.suivant();
	}
	else
		erreur("<instPour>");

	sauterSymCour("avec");
	affectation();
	seqInst();
	sauterSymCour("finpour");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
} 

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}

